package cc.shacocloud.mirage.core;

import cc.shacocloud.mirage.bean.ConfigurableBeanFactory;
import cc.shacocloud.mirage.bean.exception.BeanException;
import cc.shacocloud.mirage.env.ConfigurableEnvironment;
import cc.shacocloud.mirage.utils.converter.TypeDescriptor;
import io.vertx.core.CompositeFuture;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

import java.lang.annotation.Annotation;
import java.util.List;
import java.util.Map;
import java.util.function.Predicate;

/**
 * 基于 {@link ApplicationContext} 拓展的可配置应用上下文
 *
 * @author 思追(shaco)
 */
public interface ConfigurableApplicationContext extends ApplicationContext {
    
    /**
     * 获取当前应用内置的对象工厂
     */
    @NotNull
    ConfigurableBeanFactory getBeanFactory();
    
    /**
     * 获取当前应用内置的环境对象
     */
    @NotNull
    ConfigurableEnvironment getEnvironment();
    
    /**
     * 获取当前应用内置的事件多播器
     */
    @NotNull
    ApplicationEventMulticaster getEventMulticaster();
    
    /**
     * 启动应用
     */
    void start();
    
    /**
     * 停止应用
     */
    void stop();
    
    // ------------------------ 委托
    
    @Override
    default <T> @NotNull T getBean(@NotNull String name) throws BeanException {
        return getBeanFactory().getBean(name);
    }
    
    @Override
    default <T> @NotNull T getBean(@NotNull Class<T> classes) throws BeanException {
        return getBeanFactory().getBean(classes);
    }
    
    @Override
    default boolean containsBean(@NotNull String name) {
        return getBeanFactory().containsBean(name);
    }
    
    @Override
    default <T> boolean containsBean(@NotNull Class<T> classes) {
        return getBeanFactory().containsBean(classes);
    }
    
    @Override
    default @NotNull <T> Map<String, T> getBeanByType(@NotNull Class<T> classes) {
        return getBeanFactory().getBeanByType(classes);
    }
    
    @Override
    default @NotNull <T> Class<T> getBeanType(String name) throws BeanException {
        return getBeanFactory().getBeanType(name);
    }
    
    @Override
    default <T> String[] getBeanNamesForType(Class<T> classes) {
        return getBeanFactory().getBeanNamesForType(classes);
    }
    
    @Override
    default @NotNull <T> Map<String, Class<? extends T>> getBeanClassForType(@NotNull Class<T> classes) {
        return getBeanFactory().getBeanClassForType(classes);
    }
    
    @Override
    default <A extends Annotation> String[] getBeanNamesForAnnotation(Class<A> annotationType) {
        return getBeanFactory().getBeanNamesForAnnotation(annotationType);
    }
    
    @Override
    default <T> @Nullable T getProperty(String key, TypeDescriptor typeDescriptor) {
        return getEnvironment().getProperty(key, typeDescriptor);
    }
    
    @Override
    @NotNull
    default String resolvePlaceholders(@NotNull String text) {
        return getEnvironment().resolvePlaceholders(text);
    }
    
    @Override
    @NotNull
    default String resolveRequiredPlaceholders(@NotNull String text) throws IllegalArgumentException {
        return getEnvironment().resolveRequiredPlaceholders(text);
    }
    
    @Override
    default void addApplicationListener(ApplicationListener<?> listener) {
        getEventMulticaster().addApplicationListener(listener);
    }
    
    @Override
    default void addApplicationListeners(List<ApplicationListener<?>> listeners) {
        getEventMulticaster().addApplicationListeners(listeners);
    }
    
    @Override
    default void removeApplicationListener(ApplicationListener<?> listener) {
        getEventMulticaster().removeApplicationListener(listener);
    }
    
    @Override
    default void removeApplicationListeners(Predicate<ApplicationListener<?>> predicate) {
        getEventMulticaster().removeApplicationListeners(predicate);
    }
    
    @Override
    default void removeAllListeners() {
        getEventMulticaster().removeAllListeners();
    }
    
    @Override
    default <E extends ApplicationEvent> CompositeFuture publishEvent(E event) {
        return getEventMulticaster().publishEvent(event);
    }
}
